class_name GameControl
extends Node2D

@export var online_players: Dictionary[int, Player]
@export var single_player_mode := false
@export var players: Node2D # 玩家列表父节点
@export var PLAYER: PackedScene # 玩家预制体
@export var world: Node2D
var peer = ENetMultiplayerPeer.new() # 多人游戏API实例

static var instance: GameControl

@export var die_panel: Window

@export var input_server_ip: LineEdit
@export var input_server_port: LineEdit
@export var input_send_msg: LineEdit
@export var loading_icon: TextureRect
@export var server_ip: String = "192.168.1.105"
@export var server_port: int = 8000

@export var local_uuid: int
@export var local_player: Player
@export var player_spawn_point: Node2D
@export var world_cam: FollowCamera
@export var game_music: PackedScene
var game_music_instance: AudioStreamPlayer
@export var fps_label: Label
@export var ping_label: Label
var pings: Array = []  # 存储 ping 值的数组
var max_ping_count: int = 120  # 最多保留 120 个元素

@export var connected:= ConnectStatus.UnStart
enum ConnectStatus{
	UnStart, 
	Connecting, 
	Failed, 
	Success
}

func get_server_ip() -> String:
	#return ConfigManager.instance.load_config("network", "server_ip", server_ip)
	#return server_ip
	return input_server_ip.text
func get_server_port() -> int:
	#return ConfigManager.instance.load_config("network", "server_port", server_port)
	#return server_port
	return input_server_port.text.to_int()


func _ready() -> void:
	instance = self
	# 注册信号
	# 服务器信息
	multiplayer.peer_connected.connect(_on_peer_connected)
	multiplayer.peer_disconnected.connect(_on_peer_disconnected)
	# 客户端信号
	multiplayer.connected_to_server.connect(_on_connected_to_server)
	multiplayer.connection_failed.connect(_on_connection_failed)
	multiplayer.server_disconnected.connect(_on_server_disconnected)
	# 读取配置
	ConfigManager.read_configs()
	input_server_ip.text = ConfigManager.ip
	server_ip = ConfigManager.ip
	input_server_port.text = str(ConfigManager.port)
	server_port = ConfigManager.port
	# 专用服务器模式
	if OS.has_feature("dedicated_server"):
		LogLabel.print_log(["开启专用服务器模式"])
		_on_create_game_pressed()
	# 单人模式
	if single_player_mode:
		_on_create_game_pressed()
	pass

func _process(delta: float) -> void:
	fps_label.text = "FPS: "+str(Engine.get_frames_per_second())
	loading_icon.visible = connected == ConnectStatus.Connecting
	#if connected == ConnectStatus.Success and multiplayer.is_server():
		#print(online_players)
	pass

func _physics_process(delta: float) -> void:
	if connected == ConnectStatus.Success && local_player != null && !multiplayer.is_server():
		var current_ms = Time.get_unix_time_from_system() * 1000
		local_player.ping_request.rpc_id(1, local_uuid, current_ms)
		pass
	pass

# 当按下退出房间按钮时
func _on_exit_pressed() -> void:
	delete_game_music()
	# 如果是主机退出房间则清理所有玩家
	if multiplayer.is_server():
		for player in players.get_children():
			get_tree().queue_delete(player)
			players.remove_child(player)
	LogLabel.print_log(["已退出房间"])
	multiplayer.multiplayer_peer = null
	peer.close()
	connected = ConnectStatus.UnStart


# 当按下创建主机按钮时
func _on_create_game_pressed() -> void:
	if connected == ConnectStatus.Success: 
		LogLabel.printerr_log(["重复操作"])
		return
	if connected == ConnectStatus.Connecting: 
		LogLabel.printerr_log(["重复操作"])
		return
	LogLabel.print_log(["启动服务器: ", get_server_ip(), ":", get_server_port()])
	connected = ConnectStatus.Connecting
	var err = peer.create_server(get_server_port()) # 创建服务器
	if err != OK: # 返回码不为OK则失败退出
		LogLabel.printerr_log(["创建服务器失败, 响应码:", err])
		connected = ConnectStatus.Failed
		return
	multiplayer.multiplayer_peer = peer
	local_uuid = multiplayer.get_unique_id()
	if not OS.has_feature("dedicated_server"):
		local_player = add_player(local_uuid) # 添加玩家方法, 使用api分配的唯一ID, 注: 开服的客户端(主机)ID一般为1
		local_player.init_local_player.rpc();
		instantiate_game_music()
	LogLabel.print_log(["创建服务器完成: ", "port: ", get_server_port()])
	connected = ConnectStatus.Success
	update_online_player(local_uuid, local_player, "online")


# 当按下加入房间按钮时
func _on_join_game_pressed() -> void:
	var timeout_seconds := 3.0
	if connected == ConnectStatus.Success: 
		LogLabel.printerr_log(["重复操作"])
		return
	if connected == ConnectStatus.Connecting: 
		LogLabel.printerr_log(["重复操作"])
		return
	LogLabel.print_log(["开始连接: ", get_server_ip(), ":", get_server_port(), "...超时:", timeout_seconds, "s"])
	connected = ConnectStatus.Connecting
	
	var err = peer.create_client(get_server_ip(), get_server_port())
	if err != OK: # 返回码不为OK则失败退出
		LogLabel.printerr_log(["加入服务器失败, 响应码:", err])
		connected = ConnectStatus.Failed
		multiplayer.multiplayer_peer = null
		peer.close()
		return
	
	multiplayer.multiplayer_peer = peer
	local_uuid = multiplayer.get_unique_id()
	
	# 处理超时
	await get_tree().create_timer(timeout_seconds-1, true).timeout
	if connected == ConnectStatus.Connecting:
		LogLabel.printerr_log(["加入服务器失败: 连接超时"])
		connected = ConnectStatus.Failed
		multiplayer.multiplayer_peer = null
		peer.close()
		return


# 当有客户端连接时
func _on_peer_connected(id: int) -> void:
	# 在服务器新增玩家实体
	if multiplayer.is_server():
		LogLabel.print_log(["玩家连接到服务器: ID: ", id])
		var player = add_player(id)
		update_online_player(id, player, "online")
		#sync_online_player_skin_datas_to_player.call_deferred(player)
		#player.init_local_player.rpc();
	pass
# 当客户断开连接时
func _on_peer_disconnected(id: int) -> void:
	# 在服务器移除掉线玩家
	if !multiplayer.is_server(): return
	LogLabel.print_log(["玩家从服务器断开连接: ID: ", id])
	remove_player(id)
	update_online_player(id, online_players[id], "offline")
	pass
# 连接上服务器时
func _on_connected_to_server() -> void:
	LogLabel.print_log(["加入服务器成功"])
	connected = ConnectStatus.Success
	instantiate_game_music()
	pass
# 连接服务器失败时
func _on_connection_failed() -> void:
	#LogLabel.print_log(["回调: 加入服务器失败"])
	#multiplayer.multiplayer_peer = null
	pass
# 断开服务器连接时
func _on_server_disconnected() -> void:
	LogLabel.print_log(["从服务器断开连接, 可能: 服务器关机, 或网络断开"])
	multiplayer.multiplayer_peer = null
	pass

func add_player(id: int) -> Player:
	var player = PLAYER.instantiate() as Player # 从预制体实例化一个玩家
	player.name = str(id) # 设置玩家节点名称为id
	players.add_child(player) # 将玩家添加到player父节点下
	#player.spawn() # 初始化生成
	LogLabel.print_log(["实例化玩家: ID: ", id])
	return player

func remove_player(id: int) -> void:
	for child in players.get_children():
		var player = child as Player
		var name = player.name
		var idstr = str(id)
		if name == idstr:  # 或者根据你自己的方式来比较 id
			if is_instance_valid(player): 
				player.queue_free()
			LogLabel.print_log(["移除玩家: ID: ", id, "name: ", player.player_name()])
			return
	LogLabel.printerr_log(["移除玩家失败, 没有找到玩家: ID: ", id])


# 输入ip
func _on_input_server_ip_text_submitted(new_text: String) -> void:
	var ip = new_text
	server_ip = ip
	input_server_ip.text = ip
	ConfigManager.save_config("network", "server_ip", ip)
	pass

# 输入port
func _on_input_server_port_text_submitted(new_text: String) -> void:
	var port = new_text
	server_port = port.to_int()
	input_server_port.text = port
	ConfigManager.save_config("network", "server_port", port.to_int())
	pass

# 发送聊天消息
func _on_send_msg_text_submitted(new_text: String) -> void:
	# 仅本机玩家
	var change_text: String = input_send_msg.text
	print("调用发送信息")
	var msg := new_text
	#LogLabel.print_msg([msg])
	input_send_msg.clear()
	#a.rpc(local_uuid, msg)
	if connected != ConnectStatus.Success: return
	var player_name = local_player.player_name_label.text
	local_player.send_msg_rpc.rpc(str(local_uuid), player_name, msg)
	pass


# 显示死亡面板
func show_die_panel() -> void:
	die_panel.show()
	pass


# 重启游戏
func _on_restart_button_up() -> void:
	die_panel.hide()
	local_player.respawn()
	pass

# 退出房间
func _on_exit_button_up() -> void:
	delete_game_music()
	die_panel.hide()
	multiplayer.multiplayer_peer = null
	peer.close()
	connected = ConnectStatus.UnStart
	pass


func _on_window_close_requested() -> void:
	#die_panel.hide()
	pass


# 实例化游戏音乐
func instantiate_game_music():
	LogLabel.print_log(["实例化游戏音乐"])
	var node = game_music.instantiate()
	game_music_instance = node as AudioStreamPlayer
	get_tree().root.add_child.call_deferred(node)
	pass

# 移除游戏音乐
func delete_game_music():
	LogLabel.print_log(["移除游戏音乐"])
	get_tree().root.remove_child(game_music_instance)
	if is_instance_valid(game_music_instance): 
		game_music_instance.queue_free()
	pass


func get_cur_ping(ping: float):
	# 将新的 ping 值添加到数组中
	pings.append(ping)
	# 保证 `pings` 数组最多只有 120 个元素
	if pings.size() > max_ping_count:
		pings.remove_at(0)  # 移除最旧的 ping 值
	# 计算 ping 数组的平均值
	var avg_ping = get_average_ping()
	# 更新标签显示平均 ping
	ping_label.text = "Avg Ping: "+str(avg_ping)+" ms"
	pass

# 计算 `pings` 数组的平均值
func get_average_ping() -> float:
	if pings.size() == 0:
		return 0.0
	var total_ping: int = 0
	for ping in pings:
		total_ping += ping
	return total_ping / pings.size()


func update_online_player(id: int, player: Player, status: String): 
	if status == "online": 
		online_players[id] = player
	if status == "offline":
		online_players.erase(id)
	pass


func sync_online_player_skin_datas_to_player(newplayer: Player) -> void:
	for id in online_players.keys():
		var player = online_players[id]
		var skin_data = player.skin_data
		if id == newplayer.name.to_int(): continue
		newplayer.init_player_skin.rpc(id, skin_data)
		pass
	pass
